package com.shiyipicture.shiyipicturebackend.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shiyipicture.shiyipicturebackend.enums.SpaceLevelEnum;
import com.shiyipicture.shiyipicturebackend.enums.SpaceRoleEnum;
import com.shiyipicture.shiyipicturebackend.enums.SpaceTypeEnum;
import com.shiyipicture.shiyipicturebackend.exception.BusinessException;
import com.shiyipicture.shiyipicturebackend.exception.ErrorCode;
import com.shiyipicture.shiyipicturebackend.exception.ThrowUtils;
import com.shiyipicture.shiyipicturebackend.mapper.SpaceMapper;
import com.shiyipicture.shiyipicturebackend.model.dto.space.SpaceAddRequest;
import com.shiyipicture.shiyipicturebackend.model.entity.Picture;
import com.shiyipicture.shiyipicturebackend.model.entity.Space;
import com.shiyipicture.shiyipicturebackend.model.entity.SpaceUser;
import com.shiyipicture.shiyipicturebackend.model.entity.User;
import com.shiyipicture.shiyipicturebackend.model.vo.PictureVO;
import com.shiyipicture.shiyipicturebackend.model.vo.SpaceVO;
import com.shiyipicture.shiyipicturebackend.model.vo.UserVO;
import com.shiyipicture.shiyipicturebackend.service.SpaceService;
import com.shiyipicture.shiyipicturebackend.service.SpaceUserService;
import com.shiyipicture.shiyipicturebackend.service.UserService;

import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;


/**
 * @author Administrator
 * @description 针对表【space(空间)】的数据库操作Service实现
 * @createDate 2025-01-10 15:34:16
 */
@Service
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space>
  implements SpaceService {

  @Resource
  private UserService userService;

  @Resource
  private TransactionTemplate transactionTemplate;

  @Resource
  @Lazy
  private SpaceUserService spaceUserService;

  Map<Long, Object> lockMap = new ConcurrentHashMap<>();

  /**
   * 空键参数校验用于新增和修改
   *
   * @param space
   * @param add
   */
  @Override
  public void validSpace(Space space, boolean add) {
    ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR);
    String spaceName = space.getSpaceName();
    Integer spaceLevel = space.getSpaceLevel();
    Integer spaceType = space.getSpaceType();
    SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(spaceLevel);
    SpaceTypeEnum spaceTypeEnum = SpaceTypeEnum.getEnumByValue(spaceType);
    if (add) {
      if (StrUtil.isBlank(spaceName)) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间名称不能为空");
      }
      if (spaceLevel == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间级别不能为空");
      }
      if (spaceType == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间类型不能为空");
      }
    }
    if (spaceLevel != null && spaceLevelEnum == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间级别不存在");
    }
    if (spaceType != null && spaceTypeEnum == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间类型不存在");
    }
    if (StrUtil.isNotBlank(spaceName) && spaceName.length() > 30) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间名称过长 ");
    }
  }

  /**
   * 根据空间级别填充空间限额数据
   *
   * @param space
   */
  @Override
  public void fillSpaceBySpaceLevel(Space space) {
    ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR);
    SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(space.getSpaceLevel());
    if (spaceLevelEnum != null) {
      Long maxSize = spaceLevelEnum.getMaxSize();
      space.setMaxSize(maxSize);
      Long maxCount = spaceLevelEnum.getMaxCount();
      space.setMaxCount(maxCount);
    }
  }

  /**
   * 新增空间
   *
   * @param spaceAddRequest
   * @param loginUser
   * @return
   */
  @Override
  public long addSpace(SpaceAddRequest spaceAddRequest, User loginUser) {
    if (StrUtil.isBlank(spaceAddRequest.getSpaceName())) {
      spaceAddRequest.setSpaceName("默认空间");
    }
    if (spaceAddRequest.getSpaceLevel() == null) {
      spaceAddRequest.setSpaceLevel(SpaceLevelEnum.COMMON.getValue());
    }
    if (spaceAddRequest.getSpaceType() == null) {
      spaceAddRequest.setSpaceType(SpaceTypeEnum.PRIVATE.getValue());
    }

    Space space = new Space();
    BeanUtils.copyProperties(spaceAddRequest, space);
    fillSpaceBySpaceLevel(space);
    this.validSpace(space, true);
    if (spaceAddRequest.getSpaceLevel() != SpaceLevelEnum.COMMON.getValue() && !userService.isAdmin(loginUser)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限创建其他级别的空间");
    }
    Long userId = loginUser.getId();
    Object lock = lockMap.computeIfAbsent(userId, key -> new Object());
    try {
      synchronized (lock) {
        Long newSpaceId = transactionTemplate.execute(status -> {
          boolean exists = this.lambdaQuery().eq(Space::getUserId, userId)
            .eq(Space::getSpaceType, spaceAddRequest.getSpaceType())
            .exists();
          ThrowUtils.throwIf(exists, ErrorCode.OPERATION_ERROR, "每个用户每类空间仅能创建一个");
          boolean save = this.save(space);
          ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "操作数据库失败");
          if (SpaceTypeEnum.TEAM.getValue() == spaceAddRequest.getSpaceType()) {
            SpaceUser spaceUser = new SpaceUser();
            spaceUser.setSpaceId(space.getId());
            spaceUser.setUserId(space.getUserId());
            spaceUser.setSpaceRole(SpaceRoleEnum.ADMIN.getValue());
            save = spaceUserService.save(spaceUser);
            ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "创建团队成员记录失败");
          }

          return space.getId();
        });
        return Optional.ofNullable(newSpaceId).orElse(-1L);
      }
    } finally {
      lockMap.remove(userId);
    }
  }

  @Override
  public void checkSpaceAuth(User loginUser, Space space) {
    //仅本人或管理员可访问
    ThrowUtils.throwIf(!userService.isAdmin(loginUser) || !space.getUserId().equals(loginUser.getId()), ErrorCode.NO_AUTH_ERROR, "无权限");
  }

  @Override
  public SpaceVO getSpaceVo(Space space, HttpServletRequest request) {
    SpaceVO spaceVO = SpaceVO.objToVo(space);
    Long userId = space.getUserId();
    if (userId != null && userId > 0) {
      User user = userService.getById(userId);
      UserVO userVo = userService.getUserVo(user);
      spaceVO.setUser(userVo);
    }
    return spaceVO;
  }

  @Override
  public SpaceVO getSpaceVO(Space space, HttpServletRequest request) {
    // 对象转封装类
    SpaceVO spaceVO = SpaceVO.objToVo(space);
    // 关联查询用户信息
    Long userId = space.getUserId();
    if (userId != null) {
      User user = userService.getById(userId);
      UserVO userVo = userService.getUserVo(user);
      spaceVO.setUser(userVo);
    }
    return spaceVO;
  }


}




